package com.ncf.rpc.client;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;

import com.ncf.rpc.common.NCFRequest;
import com.ncf.rpc.common.NCFResponse;
import com.ncf.rpc.registry.ServiceDiscovery;

/**
 * RPC 代理（用于创建 RPC 服务代理）
 */
public class NCFProxy {

	private String serverAddress;
	private ServiceDiscovery serviceDiscovery;
	
	public NCFProxy(String serverAddress) {
		this.serverAddress = serverAddress;
	}
	
	public NCFProxy(ServiceDiscovery serviceDiscovery) {
		this.serviceDiscovery = serviceDiscovery;
	}
	
	
	/**
	 * 创建代理
	 */
	@SuppressWarnings("unchecked")
	public <T> T createProxy(Class<?> interfaceClass) {
		return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() {
			public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
				//创建RpcRequest，封装被代理类的属性
				NCFRequest request = new NCFRequest();
				request.setRequestId(UUID.randomUUID().toString().replaceAll("-", ""));
				//拿到声明这个方法的业务接口名称
				request.setClassName(method.getDeclaringClass().getName());
				request.setMethodName(method.getName());
				request.setParameterTypes(method.getParameterTypes());
				request.setParameters(args);
				
				//查找服务
				if (serviceDiscovery != null ){
					serverAddress = serviceDiscovery.discover();
				}
				
				System.out.println("==serverAddress==" + serverAddress);
				if(serverAddress == null){
					throw new Exception("服务地址为空");
				}
				//随机获取服务的地址
				String[] array = serverAddress.split(":");
				String host = array[0];
				
				int port = Integer.parseInt(array[1]);
				//创建Netty实现的RpcClient，链接服务端
				NCFClient client = new NCFClient(host, port);
				
				//通过netty向服务端发送请求
				NCFResponse response = client.send(request);
				
				System.out.println("=======response==========" + response);
				//response是服务端返回的数据
				//返回信息
				if(response.isError()) {
					throw response.getError();
				} else {
					return response.getResult();
				}
			}
		});
	}
	
	
}
